<template>
  <div class="fml-form-box flex-1">
    <table class="ui-form">
      <tbody>
        <template v-for="(tr,trIndex) in FormConfig.defaultConfig.tr">
          <tr
            v-if="!tr.td[0].uploadTip"
            :key="trIndex"
            :class="trIndex>1&&!showMore?'none hideTr':trIndex>1?'showTr':''"
          >
            <td
              v-for="td in tr.td"
              :key="td.name"
              :width="td.colspan2?'50%':FormConfig.defaultConfig.width || '25%'"
              :colspan="td.colspan2?'2':'1'"
              :style="td.upload?'text-align:left':''"
            >
              <el-form-item
                :label="td.label"
                class="flex"
                :label-width="FormConfig.defaultConfig.labelWidth||'80px'"
                :required="td.required"
                v-if="td.hidden?false:true"
              >
                <!-- 下拉选 -->
                <el-select
                  size="small"
                  :ref="td.refSelect"
                  v-if="td.select"
                  clearable
                  no-data-text="暂无数据"
                  :name="td.name"
                  :allow-create="td.create"
                  :multiple="td.multiSelect"
                  :multiple-limit="td.limit"
                  :filterable="td.filterable"
                  :remote="td.remote"
                  :remote-method="td.remotePagination?remoteMethod:td.remoteMethod"
                  :collapse-tags="td.tags||true"
                  v-validate="`${td.rule}`"
                  :disabled="td.disabled||false"
                  :class="{error:errorsBag.has(td.name)}"
                  v-model.trim="FormConfig.fmlForm[td.name]"
                  :placeholder="td.placeholder||td.label"
                  @focus="td.focus?inputFocus(td):null"
                >
                  <el-option
                    :ref="td.refOption"
                    v-for="select in td.selectList"
                    :key="select.value"
                    :label="select.label"
                    :value="select.value"
                  >
                    <div v-if="td.slot" class="flex">
                      <div style="width:120px;" class="ellipsis">{{ select.value }}</div>
                      <div style="flex:1">{{ select.label }}</div>
                    </div>
                  </el-option>
                </el-select>

                <!-- 单个日期 -->
                <el-date-picker
                  size="small"
                  clearable
                  :value-format="td.format?td.format:td.type!='datetime'?'yyyy-MM-dd':'yyyy-MM-dd HH:mm:00'"
                  :picker-options="td.pickerOptions||{}"
                  v-else-if="td.date && !td.daterange"
                  v-model="FormConfig.fmlForm[td.name]"
                  :name="td.name"
                  :type="td.type||'date'"
                  :class="{error:errorsBag.has(td.name)}"
                  v-validate="`${td.rule}`"
                  :ref="td.name"
                  :disabled="td.disabled||false"
                  :ddefault-value="td.defaultValue"
                  :placeholder="td.placeholder||td.label"
                ></el-date-picker>

                <!-- 模糊搜索 -->
                <el-autocomplete
                  style="width:100%"
                  v-else-if="td.autocomplete"
                  v-model.lazy.trim="FormConfig.fmlForm[td.name]"
                  size="small"
                  :name="td.name"
                  @focus="td.focus?inputFocus(td):null"
                  clearable
                  :placeholder="td.placeholder||td.label"
                  :fetch-suggestions="querySearch"
                  :trigger-on-focus="td.trigger||false"
                >
                  <i class="el-icon-edit el-input__icon" slot="suffix" v-if="td.icon"></i>
                  <template slot-scope="{ item }" v-if="td.customize">
                    <div class="name">{{ item.value }}</div>
                    <span class="addr">{{ item.label }}</span>
                  </template>
                </el-autocomplete>

                <!-- 上传图片 -->
                <el-upload
                  style="margin-top:5px;"
                  v-else-if="td.upload"
                  :ref="td.ref"
                  :show-file-list="td.showList||false"
                  :file-list="td.fileList||[]"
                  :action="actionServer"
                  :class="{'upload-disabled':td.disabled}"
                  :disabled="td.disabled"
                  :limit="td.limit"
                  :on-success="handleAvatarSuccess"
                  :on-error="handleAvatarError"
                  :auto-upload="td.autoUpload||false"
                  :multiple="td.multiple||false"
                  :list-type="td.listType||'picture-card'"
                  :accept="td.accept||''"
                  :before-upload="beforeUpload"
                  :on-exceed="exceedHandle"
                  :on-preview="picturePreview"
                  :before-remove="beforeRemove"
                  @click.native.stop="getCurrentUpload(td)"
                >
                  <i
                    slot="trigger"
                    size="small"
                    type="primary"
                    class="iconfont icon-shangchuanfujian fml-upload-icon"
                    :class="td.disabled?'upload-disabled':''"
                    v-if="td.listType=='text'"
                  ></i>
                  <i
                    class="el-icon-plus"
                    slot="trigger"
                    style="border:none"
                    :class="{'upload-disabled':td.disabled}"
                    v-else
                  ></i>
                  <input
                    class="fml-upload-hidden"
                    style="height:0;border:none"
                    :id="td.ref+'-hidden'"
                    type="text"
                    :class="{error:errorsBag.has(td.name)}"
                    v-validate="`${td.rule}`"
                    :name="td.name"
                    v-model.lazy.trim="FormConfig.fmlForm[td.name]"
                  />
                </el-upload>

                <!-- 下拉树 -->
                <div class="fml-input-tree" v-else-if="td.tree">
                  <div @click="showTreeHandle(td)">
                    <el-input
                      size="small"
                      :autofocus="td.autofocus||false"
                      auto-complete="off"
                      tabindex="treeInput"
                      :prefix-icon="td.prefixIcon"
                      :suffix-icon="td.suffixIcon"
                      clearable
                      :placeholder="td.placeholder?td.placeholder:td.label"
                      type="text"
                      :readonly="true"
                      :name="td.name"
                      v-model.trim="FormConfig.defaultConfig.treeText[td.ref]"
                      :disabled="td.disabled||false"
                      @blur="td.blur?inputBlur(td):null"
                      v-validate="`${td.rule}`"
                      :id="td.refOut"
                      :class="{error:errorsBag.has(td.name)}"
                      @focus="td.focus?inputFocus(td):null"
                    ></el-input>
                  </div>
                  <input
                    :name="td.name"
                    type="hidden"
                    v-model.lazy.trim="FormConfig.fmlForm[td.name]"
                  />
                  <div
                    class="fml-tree-box"
                    :style="{'padding-bottom':td.checkbox?'50px':0}"
                    v-show="treeStyle[td.treeIdentity]||false"
                  >
                    <el-input
                      class="filter-tree"
                      v-if="td.showFilter"
                      size="small"
                      clearable
                      tabindex="treeInput"
                      placeholder="输入关键字进行过滤"
                      v-model.lazy.trim="filterText"
                    ></el-input>
                    <el-tree
                      :style="{maxHeight:(td.maxHeight||200)+'px'}"
                      class="filter-tree"
                      clearable
                      :data="td.treeData"
                      :props="td.defaultProps"
                      :filter-node-method="filterNode"
                      :lazy="td.lazy||false"
                      :load="td.loadNode"
                      :accordion="td.accordion||true"
                      :empty-text="td.emptyText||'暂无数据'"
                      :highlight-current="td.highlight||true"
                      :default-expand-all="td.expandAll||false"
                      :expand-on-click-node="td.expandClickNode||false"
                      :check-on-click-node="td.checkClickNode||false"
                      :default-expanded-keys="td.defaultExpand||[]"
                      :show-checkbox="td.checkbox||false"
                      :check-strictly="td.strictly||false"
                      :node-key="td.nodekey||''"
                      :default-checked-keys="FormConfig.fmlForm[td.name]?String(FormConfig.fmlForm[td.name]).split(','):[]"
                      :icon-class="td.icon||''"
                      :current-node-key="FormConfig.fmlForm[td.name]?Number(FormConfig.fmlForm[td.name]):''"
                      @node-click="treeNodeClick"
                      @check="treeNodeCheck"
                      :ref="td.ref"
                    ></el-tree>
                    <span slot="footer" v-if="!td.checkbox" class="tree-footer">
                      <el-button
                        size="mini"
                        @click="FormConfig.fmlForm[td.name]='';FormConfig.defaultConfig.treeText[td.ref]=''"
                      >清 空</el-button>
                    </span>
                    <span slot="footer" v-if="td.checkbox" class="tree-footer">
                      <el-button size="mini" @click="treeBtnClick(td.treeIdentity)">关 闭</el-button>
                    </span>
                  </div>
                </div>

                <!-- 级联 -->
                <el-cascader
                  v-else-if="td.cascader"
                  :options="td.options"
                  :name="td.name"
                  :ref="td.ref"
                  clearable
                  size="small"
                  :props="td.props||{value:'value',label:'label',children:'children'}"
                  v-validate="`${td.rule}`"
                  :disabled="td.disabled||false"
                  :class="{error:errorsBag.has(td.name)}"
                  v-model.trim="FormConfig.fmlForm[td.name]"
                ></el-cascader>

                <!-- 查询按钮合并 -->
                <el-button
                  type="primary"
                  size="small"
                  icon="el-icon-search"
                  @click.native="searchHandle"
                  v-else-if="td.searchBtn"
                >查询</el-button>

                <!-- 普通型文本框 -->
                <el-input
                  v-else
                  size="small"
                  :ref="td.ref"
                  :autofocus="td.autofocus||false"
                  auto-complete="off"
                  :prefix-icon="td.prefixIcon"
                  :suffix-icon="td.suffixIcon"
                  :min="td.min||''"
                  :max="td.max||''"
                  clearable
                  show-word-limit
                  resize="none"
                  v-model.lazy.trim="FormConfig.fmlForm[td.name]"
                  :name="td.name"
                  :placeholder="td.placeholder||td.label"
                  :type="td.type||'text'"
                  :rows="td.rows||3"
                  :readonly="td.readonly||false"
                  :disabled="td.disabled||false"
                  :maxlength="td.maxlength||''"
                  v-validate="`${td.rule}`"
                  @blur="td.blur?inputBlur(td):null"
                  @focus="td.focus?inputFocus(td):null"
                  @change="td.change?inputChange(td):null"
                  :class="{error:errorsBag.has(td.name)}"
                ></el-input>
                <span
                  class="help is-danger"
                  v-show="errorsBag.has(td.name)"
                >{{ errorsBag.first(td.name) }}</span>
                <form style="display:none" v-if="td.type=='password'">
                  <!-- 此处为了避免记住密码自动填充 -->
                  <input type="password" name="password" />
                </form>
                <input
                  type="password"
                  name="userPassword"
                  v-if="td.type=='password'"
                  style="width:0;height:0;float:left;visibility:hidden"
                />
              </el-form-item>
            </td>
            <td :colspan="(FormConfig.defaultConfig.width=='25%'?4:2)%tr.td.length"></td>
          </tr>
          <tr v-if="FormConfig.defaultConfig.uploadAccept&&tr.td[0].uploadTip" :key="trIndex">
            <td style="padding-bottom:10px">请上传{{tr.td[0].accept}}格式的文件</td>
          </tr>
        </template>
      </tbody>
    </table>
    <el-dialog :visible.sync="imgBigVisible" title="查看" :append-to-body="true">
      <img width="100%" :src="imgBigUrl" v-if="imgBigUrl" />
      <div class="flex" v-else>图片加载中,请稍后....</div>
    </el-dialog>
  </div>
</template>
<script lang="ts">
  import { Component,Emit, Inject,Model,Prop,Provide,Vue, Watch} from "vue-property-decorator";
  import { State } from "vuex-class";
  import { fmlRequest } from "../utils";

  var parentIndex = 0; //父级
  var child1 = 0; //1级索引
  var child2 = 0; //2级索引
  var child3 = 0; //3级索引
  @Component({
    components:{}
  })
  export default class fmlInput extends Vue {
    actionServer: string = ''; //自动上传服务器地址
    filterText: string = ""; //树当前检索的值
    currentTree: string = ""; //当前操作的树ref，解决一个页面多个树
    currentTreeBlur: string = ""; //下拉树异步校验问题
    imgBigVisible: boolean = false; //查看大图
    imgBigUrl: string = ""; //大图地址
    ref: string = ""; //当前操作项
    limit:number=5;//可上传的文件数量
    searchParam: any = {}; //表单查询的值

    @Prop({ default: false })
    showMore: Boolean; //当表单查询超过两行则隐藏剩下的
    @Prop()
    FormConfig: any; //表单配置

    @State treeStyle: any; //当前操作的树
    @Watch("filterText")
    onFilterText(val) {
      if (!this.$refs[this.currentTree] || !this.$refs[this.currentTree][0])
        return;
      this.$refs[this.currentTree][0].filter(val);
    }
    // 查询按钮合并表单时查询
    searchHandle() {
      this.searchParam = this.FormConfig.fmlForm;
      var roles = {},
        organIds = {};
      // 角色复选
      if (
        this.searchParam &&
        this.searchParam.roleIds &&
        this.searchParam.roleIds.length > 0
      ) {
        roles = { roleIds: this.searchParam.roleIds.join(",") };
      }
      // 机构复选
      if (
        this.searchParam &&
        this.searchParam.organIds &&
        this.searchParam.organIds.length > 0
      ) {
        organIds = { organIds: this.searchParam.organIds.join(",") };
      }
      //判断查询值是否改变
      if (this.$store.state.searchParam == this.searchParam) {
        this.$store.commit("setUpdateTable");
        return;
      }
      this.$store.commit("setSearchParam", {
        ...this.searchParam,
        ...roles,
        ...organIds
      });
    }
    // tree的操作按钮
    treeBtnClick(ref) {
      this.treeStyle[ref] = false;
      this.$store.commit("setTreeStyle", this.treeStyle);
    }
    //过滤
    filterNode(value, data) {
      if (!value) return true;
      let label = this.FormConfig.defaultConfig.defaultProps[this.currentTree][0];
      return data[label].indexOf(value) !== -1;
    }
    // 复选节点单击
    treeNodeCheck(obj, bol) {
      let label = this.FormConfig.defaultConfig.defaultProps[this.currentTree][0];
      let id = this.FormConfig.defaultConfig.defaultProps[this.currentTree][1];
      this.FormConfig.defaultConfig.treeText[this.currentTree] = "";
      this.FormConfig.fmlForm[this.currentTree] = "";
      if (!bol || !bol.checkedNodes) return;
      let labels = [];
      let value = [];
      bol.checkedNodes.map(item => {
        labels.push(item[label]);
        value.push(item[id]);
      });
      this.FormConfig.defaultConfig.treeText[this.currentTree] = labels.join(",");
      this.FormConfig.fmlForm[this.currentTree] = value.join(",");
      setTimeout(() => {
        document.getElementById(this.currentTreeBlur).focus();
        document.getElementById(this.currentTreeBlur).blur();
      }, 5);
    }
    // 节点单击
    treeNodeClick(obj, node, self, e) {
      let label = this.FormConfig.defaultConfig.defaultProps[this.currentTree][0];
      let id = this.FormConfig.defaultConfig.defaultProps[this.currentTree][1];
      this.FormConfig.defaultConfig.treeText[this.currentTree] = "";
      this.FormConfig.fmlForm[this.currentTree] = "";
      if (self.showCheckbox && self.tree.checkOnClickNode) {
        let checkNode = this.$refs[this.currentTree][0].getCheckedNodes();
        let labels = [];
        let value = [];
        checkNode.map(item => {
          labels.push(item[label]);
          value.push(item[id]);
        });
        this.FormConfig.defaultConfig.treeText[this.currentTree] = labels.join(
          ","
        );
        this.FormConfig.fmlForm[this.currentTree] = value.join(",");
      } else if (!self.showCheckbox) {
        this.FormConfig.defaultConfig.treeText[this.currentTree] = obj[label];
        this.FormConfig.fmlForm[this.currentTree] = obj[id];
        for (var key in this.treeStyle) {
          this.treeStyle[key] = false;
        }
      }
      setTimeout(() => {
        document.getElementById(this.currentTreeBlur).focus();
        document.getElementById(this.currentTreeBlur).blur();
      }, 5);
    }
    //图片懒加载
    loadImageAsync(item, resolve, reject) {
      let image = new Image();
      image.src = item.src;
      image.onload = function() {
        resolve({
          naturalHeight: image.naturalHeight,
          naturalWidth: image.naturalWidth,
          src: image.src
        });
      };
      image.onerror = function(e) {
        reject(e);
      };
    }
    // 查看大图
    picturePreview(file) {
      let img = ["jpg", "png", "svg", "jpeg", "gif"];
      if (
        (file.response &&
          img.indexOf(file.response.data.suffix.toLowerCase()) == -1) ||
          img.indexOf(file.accept.toLowerCase()) == -1
        ) {
        window.location.href = file.response
          ? this.$fmlDomain + "/" + file.response.data.url
          : this.$fmlDomain + "/" + file.url;
      } else {
        this.imgBigVisible = true;
        this.loadImageAsync('',res => {
            this.imgBigUrl = res.src;
          },
          err => {
            this.imgBigUrl = "";
            this.$message({
              type: "error",
              message: "图片加载失败",
              showClose: true
            });
            this.imgBigVisible = false;
          }
        );
      }
    }
    // 超过张数
    exceedHandle(file, fileList) {
      let limit = this.limit; ////拿到当前操作的upload
      return this.$message({
        showClose: true,
        type: "warning",
        message: "图片不能超过" + limit + "张"
      });
    }
    // 自动上传成功
    handleAvatarSuccess(res, file) {
      if (!res.success) {
        this.$message({ type: "error", message: "上传失败", showClose: true });
        this.$refs[this.ref][0].uploadFiles.pop();
        return;
      }
      this.$store.state.fileIds.push(res.data.id);
      this.FormConfig.fmlForm[this.ref] = this.$store.state.fileIds;
      let hidden = this.ref + "-hidden";
      setTimeout(() => {
        document.getElementById(hidden).focus();
        document.getElementById(hidden).blur();
      }, 500);
    }
    //上传失败
    handleAvatarError(err, file, fileList) {
      this.$message({
        type: "error",
        message: err.message || "上传失败",
        showClose: true
      });
    }
    // 上传前
    beforeUpload(file) {
      // 这里可以特许处理
      let isUpload = this.FormConfig.defaultConfig.uploadAccept;
      if (!this.FormConfig.defaultConfig.uploadAccept || !isUpload) return true;
      if (!isUpload.test(file.name)) {
        this.$message.error(
          "请上传符合 png, jpeg,jpg, doc, docx, pdf, zip, rar, tar 格式文件!"
        );
        let files = this.$refs[this.ref][0].uploadFiles;
        files.map((item, index) => {
          if (item.name == file.name) {
            setTimeout(() => {
              this.$refs[this.ref][0].uploadFiles.splice(index, 1);
            }, 100);
          }
        });
      }
      return isUpload.test(file.name);
    }
    // 删除
    async beforeRemove(file, fileList) {
      let imgArr = this.FormConfig.fmlForm[this.ref]; ////拿到当前操作的upload
      let id = file.response.data.id;
      let [err, result] = await this.$fetchService({ id: id },'fileList',true);
      if (err) {
        return this.$message({
          type: "error",
          message: err.message || "删除文件失败",
          showClose: true
        });
      }
      this.$message({ type: "success", message: "删除成功", showClose: true });
      setTimeout(() => {
        let fileId =
          this.$store.state.fileIds.indexOf(id) > -1
            ? this.$store.state.fileIds.splice(
                this.$store.state.fileIds.indexOf(id),
                1
              )
            : this.$store.state.fileIds;
        this.FormConfig.fmlForm[this.ref] = this.$store.state.fileIds;
      });
    }
    getCurrentUpload(td) {
      this.limit=td.limit
      this.ref = td.ref; //当前操作的对象
    }
    // 校验
    callMethod() {
      this.$validator.validateAll().then(result => {
        this.$emit("getValidate", result);
      });
    }
    // 清空校验
    clearValidate() {
      this.$validator.reset();
    }
    // 普通输入框失去焦点事件
    inputBlur(td) {
      if (!td.blur) return;
      this.$store.commit("setInputBlur");
      this.$store.commit("setInputName", td.name);
    }
    // 普通输入框change事件
    inputChange(td) {
      if (!td.change) return;
      this.$store.commit("setInputChange");
      this.$store.commit("setInputName", td.name);
    }
    // 输入框单击
    showTreeHandle(td) {
      if (String(td.disabled) == "true") return;
      this.filterText = "";
      if (td.tree) {
        //是否树
        this.$refs[td.ref][0].filter("");
        this.currentTree = td.ref;
        this.currentTreeBlur = td.refOut; //解决下拉树选中输入框异步校验问题
        this.treeStyle[td.treeIdentity] = true;
        for (var key in this.treeStyle) {
          if (key != td.treeIdentity) {
            this.treeStyle[key] = false;
          }
        }
        this.$store.commit("setTreeStyle", this.treeStyle);
      }
    }
    //普通输入框获取焦点事件
    inputFocus(td) {
      if (!td.focus) return;
      this.$store.commit("setInputFocus");
      this.$store.commit("setInputName", td.name);
    }
    // 输入建议
    querySearch(queryString, cb) {
      if (!this.$store.state.autoSearchData) return;
      var restaurants = this.$store.state.autoSearchData;
      var results = queryString
        ? restaurants.filter(this.createFilter(queryString))
        : restaurants;
      // 调用 callback 返回建议列表的数据
      cb(results);
    }
    createFilter(queryString) {
      return restaurant => {
        return (
          restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
        );
      };
    }
    mounted() {
      // 处理表单校验
      this.$nextTick(function() {
        this.$on("callMethod", function() {});
        this.$on("clearValidate", () => {});
        // this.$on("uploadAutoFile", () => {});
        let that = this;
        // 单击其他地方清除树结构
        document.onclick = function(e) {
          // 处理多个下拉树显示下拉框问题
          if (
            !e.target.attributes.tabIndex ||
            e.target.attributes.tabIndex.nodeValue != "treeInput"
          ) {
            for (var key in that.treeStyle) {
              that.treeStyle[key] = false;
            }
            that.$store.commit("setTreeStyle", that.treeStyle);
          }
        };

        let treetext = that.FormConfig.defaultConfig.treeText;
        if (treetext) {
          for (var key in treetext) {
            let label = that.FormConfig.defaultConfig.defaultProps[key]
              ? that.FormConfig.defaultConfig.defaultProps[key][0]
              : "label";
            let treekey = that.FormConfig.fmlForm[key];
            if (
              (treekey || String(treekey) == "0") &&
              String(treekey).split(",").length > 0
            ) {
              if (that.$refs[key][0] && that.$refs[key][0].showCheckbox) {
                let result = that.$refs[key][0].getCheckedNodes();
                let res = [];
                result.map(item => {
                  res.push(item[label]);
                });
                that.FormConfig.defaultConfig.treeText[key] = that.FormConfig
                  .defaultConfig.treeText[key]
                  ? that.FormConfig.defaultConfig.treeText[key]
                  : res.join(",");
              } else {
                let result = that.$refs[key][0].getCheckedNodes();
                that.FormConfig.defaultConfig.treeText[key] = that.FormConfig
                  .defaultConfig.treeText[key]
                  ? that.FormConfig.defaultConfig.treeText[key]
                  : result[0][label];
              }
            }
          }
        }
      });
    }
    created() {
      this.actionServer=this.$fetchService.fmlUpload
      this.$store.commit("resetTreeStyle");
      this.$store.state.fileIds = [];
    }
  }
</script>

<style scoped>
.upload-disabled .el-upload {
  cursor: not-allowed;
}
.fml-upload-icon {
  width: 40px;
  height: 40px;
  cursor: pointer;
  line-height: 35px;
  font-size: 20px;
  border-radius: 5px;
  text-align: center;
  color: #4a8ccf;
  border: 1px solid #cdcdcd;
  display: inline-block;
}
.fml-upload-icon:hover {
  border-color: #4a8ccf;
}
.fml-upload-icon.upload-disabled {
  cursor: not-allowed;
  color: #cdcdcd;
}
.fml-upload-icon.upload-disabled:hover {
  border-color: #cdcdcd;
}
</style>

